package org.tamal.jsf.bean;

import java.io.UnsupportedEncodingException;
import java.util.Properties;
import java.util.logging.Logger;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.tamal.SessionKey;

import com.google.appengine.api.datastore.Entity;

/**
 * This bean is used for sending email.
 * @author Tamal Kanti Nath
 */
@ManagedBean
public final class SendEmail {

    private static final String DOMAIN = "@tamalnath.appspotmail.com";
    private final Logger log = Logger.getLogger(getClass().getName());
    private Entity user;
    private String from = "Administrator <admin@tamalnath.appspotmail.com>";
    private String to;
    private String cc;
    private String bcc;
    private String subject;
    private String body;

    /**
     * Set the logged in user's email in the TO field.
     */
    public SendEmail() {
        user = (Entity) FacesContext.getCurrentInstance()
                .getExternalContext().getSessionMap()
                .get(SessionKey.USER.name());
        if (user == null) {
            return;
        }
        String name = (String) user.getProperty("name");
        String email = (String) user.getProperty("email");
        try {
            to = new InternetAddress(email, name).toUnicodeString();
        } catch (UnsupportedEncodingException e) {
            log.throwing(getClass().getName(), "Email", e);
        }
    }
 
    /**
     * Return the from email address.
     * @return the from
     */
    public String getFrom() {
        return from;
    }

    /**
     * Sets the from email address.
     * @param from the from to set
     */
    public void setFrom(String from) {
        this.from = from;
    }

    /**
     * Return the to email address.
     * @return the to
     */
    public String getTo() {
        return to;
    }

    /**
     * Sets the to email address.
     * @param to the to to set
     */
    public void setTo(String to) {
        this.to = to;
    }

    /**
     * Return the cc email address.
     * @return the cc
     */
    public String getCc() {
        return cc;
    }

    /**
     * Sets the cc email address.
     * @param cc the cc to set
     */
    public void setCc(String cc) {
        this.cc = cc;
    }

    /**
     * Return the bcc email address.
     * @return the bcc
     */
    public String getBcc() {
        return bcc;
    }

    /**
     * Sets the bcc email address.
     * @param bcc the bcc to set
     */
    public void setBcc(String bcc) {
        this.bcc = bcc;
    }

    /**
     * Return the subject.
     * @return the subject
     */
    public String getSubject() {
        return subject;
    }

    /**
     * Sets the subject.
     * @param subject the subject to set
     */
    public void setSubject(String subject) {
        this.subject = subject;
    }

    /**
     * Return the body.
     * @return the body
     */
    public String getBody() {
        return body;
    }

    /**
     * Sets the body.
     * @param body the body to set
     */
    public void setBody(String body) {
        this.body = body;
    }

    /**
     * Execute the email program.
     */
    public void execute() {
        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);
        FacesMessage msg;
        try {
            Message mail = new MimeMessage(session);
            InternetAddress[] address = InternetAddress.parseHeader(from, true);
            mail.setFrom(address[0]);
            address = InternetAddress.parseHeader(to, true);
            mail.addRecipients(RecipientType.TO, address);
            address = InternetAddress.parseHeader(cc, true);
            mail.addRecipients(RecipientType.CC, address);
            address = InternetAddress.parseHeader(bcc, true);
            mail.addRecipients(RecipientType.BCC, address);
            mail.setSubject(subject);
            mail.setText(body);
            validateEmailAddresses(mail.getAllRecipients());
            Transport.send(mail);
            msg = new FacesMessage("message sent");
        } catch (MessagingException e) {
            log.throwing(getClass().getName(), "execute", e);
            msg = new FacesMessage(e.getMessage());
        }
        FacesContext.getCurrentInstance().addMessage("msg", msg);
    }

    private void validateEmailAddresses(Address[] addresses) throws MessagingException {
        String userEmail = null;
        if (user != null) {
            userEmail = (String) user.getProperty("email");
        }
        for (Address address : addresses) {
            String email = ((InternetAddress) address).getAddress();
            if (email.equals(userEmail) || email.endsWith(DOMAIN)) {
                continue;
            }
            throw new AddressException("Restricted address", email);
        }
    }
}
